import 'package:flutter/material.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
import 'package:flutter_components_web/cons/constant.dart';
import 'package:flutter_components_web/utils/three_js/model_helper.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:three_js/three_js.dart' as three;
import 'dart:math' as math;
import '../../utils/three_js/light_helper.dart';
import '../shared/com_button.dart';

class Com3dThreeJsModel extends StatefulWidget {
  const Com3dThreeJsModel({super.key});

  @override
  State<Com3dThreeJsModel> createState() => _Com3dThreeJsModelState();
}

class _Com3dThreeJsModelState extends State<Com3dThreeJsModel>
    with LightHelper, ModelHelper, Constants {
  late three.ThreeJS threeJs;
  late three.OrbitControls controls;
  late List<three.Object3D> objects;

  @override
  void initState() {
    threeJs = three.ThreeJS(
      onSetupComplete: () {
        setState(() {});
      },
      setup: setup,
      settings: three.Settings(
        enableShadowMap: true, // 启用阴影
        useOpenGL: true, // 使用 WebGL
        toneMapping: three.ACESFilmicToneMapping, // 电影级色调
      ),
    );
    objects = [];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(children: [threeJs.build(), _buildControlOperations()]),
    );
  }

  @override
  void dispose() {
    threeJs.dispose();
    three.loading.clear();
    super.dispose();
  }

  Future<void> setup() async {
    threeJs.scene = three.Scene();
    // 打光
    final lights = getCustomLight();
    threeJs.scene.add(lights.$1);
    threeJs.scene.add(lights.$2);
    threeJs.scene.add(lights.$3);

    /// 摄像机
    threeJs.camera = three.PerspectiveCamera(
      10, // 视野角度 越大，看到的东西越多，跟手机拍照开了超广角一样
      threeJs.width / threeJs.height, // 宽高比
      1, // 最小渲染距离
      1000, // 最大渲染距离
    );
    threeJs.camera.position.setValues(0, 40, 100); // x,y,z
    controls = three.OrbitControls(threeJs.camera, threeJs.globalKey);
    controls.update();

    // 加载模型
    final gltf = await three.GLTFLoader()
        .setPath(modelsFilePath)
        .fromAsset(foxModel);
    gltf!.scene.traverse((child) {
      if (child is three.Mesh) {
        objects.add(child);
      }
    });
    gltf.scene.castShadow = true;
    threeJs.scene.add(gltf.scene);

    // 创建一个地面
    final groundGeometry = three.PlaneGeometry(10, 10);
    final groundMaterial = three.MeshStandardMaterial({
      three.MaterialProperty.color: 0xcccccc, // 地面颜色（灰色）
      three.MaterialProperty.roughness: 0.8, // 表面粗糙度（0-1）
      three.MaterialProperty.metalness: 0.2, // 金属感（0-1）
      three.MaterialProperty.side: three.DoubleSide, // 双面渲染（可选）
    });
    final ground = three.Mesh(groundGeometry, groundMaterial);
    ground.rotation.x = -math.pi / 2; // 绕X轴旋转90度（使其水平）
    ground.position.y = -0.1; // 稍微下移（避免与其他物体重叠）
    ground.receiveShadow = true;
    threeJs.scene.add(ground);
  }

  Widget _buildControlOperations() {
    if (!threeJs.mounted) return Container();
    return Positioned(
      bottom: 0,
      child: Wrap(
        children: [
          Container(
            padding: EdgeInsets.all(10.r),
            decoration: BoxDecoration(
              color: Colors.white,
              borderRadius: BorderRadius.circular(5.r),
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children:
                  objects.map((object) {
                    final color = three.Color();
                    final colorValue =
                        (color..setFrom(object.material!.color)).getHex();
                    return _buildColorPicker(
                      colorValue: colorValue,
                      label: object.name,
                      object: object,
                      context: context,
                    );
                  }).toList(),
            ),
          ),
        ],
      ),
    );
  }

  // 颜色选择器
  Widget _buildColorPicker({
    required int colorValue,
    required String label,
    required three.Object3D object,
    required BuildContext context,
  }) {
    final r = (0xff0000 & colorValue) >> 16;
    final g = (0x00ff00 & colorValue) >> 8;
    final b = (0x0000ff & colorValue) >> 0;
    final color = Color.fromARGB(255, r, g, b);
    return Container(
      margin: EdgeInsets.only(top: 5.r),
      child: Row(
        children: [
          Container(
            width: 20.r,
            height: 20.r,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(10.r),
              border: Border.all(color: Colors.black),
              color: color,
            ),
          ),
          Container(
            width: 100.r,
            padding: EdgeInsets.symmetric(horizontal: 10.r),
            child: Text(
              label,
              style: TextStyle(fontSize: 15.r),
              overflow: TextOverflow.ellipsis,
            ),
          ),
          InkWell(
            onTap:
                () => pickColorDialog(
                  color: color,
                  object: object,
                  context: context,
                ),
            child: Container(
              width: 150.r,
              height: 30.r,
              decoration: BoxDecoration(
                color: color,
                borderRadius: BorderRadius.all(Radius.circular(5)),
                border: Border.all(color: Colors.black),
              ),
            ),
          ),
        ],
      ),
    );
  }

  // 选择颜色弹窗
  pickColorDialog({
    required Color color,
    required three.Object3D object,
    required BuildContext context,
  }) {
    Color onChangeColor = color;
    showDialog(
      context: context,
      builder: (ctx) {
        return AlertDialog(
          title: Text(pickAColorConstant, style: TextStyle(fontSize: 15.r)),
          content: SizedBox(
            width: 250.r,
            child: ColorPicker(
              pickerColor: color,
              onColorChanged: (color) {
                onChangeColor = color;
              },
              colorPickerWidth: 240.r,
              pickerAreaHeightPercent: 1,
              portraitOnly: true,
              enableAlpha: false,
              labelTypes: const [],
              pickerAreaBorderRadius: BorderRadius.circular(5),
            ),
          ),
          actions: [
            ComButton(
              text: okConstant,
              textColor: Colors.black,
              bgColor: Colors.white,
              onTap: () {
                object.material?.color.setFromHex32(onChangeColor.toARGB32());
                setState(() {});
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }
}
